package com.hifar.sso.interceptor;

import com.hifar.sso.model.SSOUser;
import com.hifar.sso.service.SSOAuthService;
import com.hifar.sso.util.SSOConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * SSO认证拦截器
 *
 * @author system
 * @since 1.0.0
 */
@Component
public class SSOAuthInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(SSOAuthInterceptor.class);

    @Autowired
    private SSOAuthService ssoAuthService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {
            String requestURI = request.getRequestURI();
            logger.debug("SSO拦截器处理请求: {}", requestURI);

            // 跳过不需要认证的路径
            if (isExcludedPath(requestURI)) {
                return true;
            }

            // 检查会话认证
            if (checkSessionAuth(request)) {
                return true;
            }

            // 检查Token认证
            if (checkTokenAuth(request)) {
                return true;
            }

            // 认证失败，返回401
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":401,\"message\":\"未授权访问\"}");
            return false;

        } catch (Exception e) {
            logger.error("SSO拦截器处理异常", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":500,\"message\":\"认证服务异常\"}");
            return false;
        }
    }

    /**
     * 检查是否为排除路径
     */
    private boolean isExcludedPath(String requestURI) {
        String[] excludedPaths = {
                "/sso/login",
                "/sso/authorize",
                "/sso/authorize/confirm",
                "/sso/token",
                "/sso/logout",
                "/sso/status"
        };

        for (String path : excludedPaths) {
            if (requestURI.startsWith(path)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 检查会话认证
     */
    private boolean checkSessionAuth(HttpServletRequest request) {
        try {
            HttpSession session = request.getSession(false);
            if (session == null) {
                return false;
            }

            SSOUser user = (SSOUser) session.getAttribute("user");
            if (user == null) {
                return false;
            }

            // 将用户信息设置到请求属性中
            request.setAttribute("currentUser", user);

            logger.debug("会话认证成功，用户ID: {}", user.getUserId());
            return true;

        } catch (Exception e) {
            logger.error("检查会话认证异常", e);
            return false;
        }
    }

    /**
     * 检查Token认证
     */
    private boolean checkTokenAuth(HttpServletRequest request) {
        try {
            String accessToken = getAccessTokenFromRequest(request);
            if (accessToken == null) {
                return false;
            }

            // 验证Token
            SSOUser user = ssoAuthService.validateToken(accessToken);
            if (user == null) {
                return false;
            }

            // 将用户信息设置到请求属性中
            request.setAttribute("currentUser", user);

            logger.debug("Token认证成功，用户ID: {}", user.getUserId());
            return true;

        } catch (Exception e) {
            logger.error("检查Token认证异常", e);
            return false;
        }
    }

    /**
     * 从请求中获取访问令牌
     */
    private String getAccessTokenFromRequest(HttpServletRequest request) {
        // 从Authorization头获取
        String authHeader = request.getHeader(SSOConstants.HEADER_AUTHORIZATION);
        if (StringUtils.hasText(authHeader) && authHeader.startsWith(SSOConstants.TOKEN_TYPE_BEARER + " ")) {
            return authHeader.substring(7);
        }

        // 从请求参数获取
        String tokenParam = request.getParameter(SSOConstants.PARAM_ACCESS_TOKEN);
        if (StringUtils.hasText(tokenParam)) {
            return tokenParam;
        }

        return null;
    }
}
